package com.scs.application.modules.upms.security.authenticator;

import com.scs.application.modules.upms.security.integration.authenticator.IntegrationAuthentication;
import com.scs.application.modules.upms.security.integration.authenticator.IntegrationAuthenticator;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 */
public class IntegrationAuthenticationProcess {

    public static final String AUTH_TYPE_PARM_NAME = "auth_type";

    private Collection<IntegrationAuthenticator> authenticators;

    private ApplicationContext applicationContext;

    @Bean("defaultIntegrationUserDetailsService")
    @ConditionalOnMissingBean(IntegrationUserDetailsService.class)
    public IntegrationUserDetailsService userDetailsService() {
        return new IntegrationUserDetailsService();
    }

    public void process(Map<String, Object> loginParams) {

        //设置集成登录信息
        IntegrationAuthentication integrationAuthentication = new IntegrationAuthentication();
        integrationAuthentication.setAuthType(loginParams.get(AUTH_TYPE_PARM_NAME).toString());
        integrationAuthentication.setAuthParameters(loginParams);

        this.prepare(integrationAuthentication);
        //后置处理
        this.complete(integrationAuthentication);

        userDetailsService().setIntegrationAuthenticators((List<IntegrationAuthenticator>) authenticators);
    }

    /**
     * 进行预处理
     *
     * @param integrationAuthentication
     */
    private void prepare(IntegrationAuthentication integrationAuthentication) {

        //延迟加载认证器
        if (this.authenticators == null) {
            synchronized (this) {
                Map<String, IntegrationAuthenticator> integrationAuthenticatorMap = applicationContext.getBeansOfType(IntegrationAuthenticator.class);
                if (integrationAuthenticatorMap != null) {
                    this.authenticators = integrationAuthenticatorMap.values();
                }
            }
        }

        if (this.authenticators == null) {
            this.authenticators = new ArrayList<>();
        }

        for (IntegrationAuthenticator authenticator : authenticators) {
            if (authenticator.support(integrationAuthentication)) {
                authenticator.prepare(integrationAuthentication);
            }
        }
    }

    /**
     * 后置处理
     *
     * @param integrationAuthentication
     */
    private void complete(IntegrationAuthentication integrationAuthentication) {
        for (IntegrationAuthenticator authenticator : authenticators) {
            if (authenticator.support(integrationAuthentication)) {
                authenticator.complete(integrationAuthentication);
            }
        }
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
